import core from '@/core/'
import {getDbName} from '../async/'
import {getSpaceBase} from '../sync/'

/**
 * 获取用户信息
 * 优先从缓存中读取，缓存中没有的，再请求数据
 */
const getUserInfo = (cloud, space, name, field, ids, reuserinfo) => {
	return new Promise((resolve, reject) => {
		// 需要请求的用户id，需要读取的用户id
		const fids = [], rids = []
		ids.map(id => {
			if (reuserinfo || core.storage.userInfoIds.indexOf(id) === -1) {
				fids.push(id)
			} else {
				rids.push(id)
			}
		})
		const arr = []
		if (rids.length > 0) {
			// 读取用户信息
			rids.map(id => {
				var json = core.storage.getDataSync(`${id}_user`)
				if (json) {
					json = JSON.parse(json)
					arr.push(json)
				} else {
					// 不存在的，仍旧请求
					fids.push(id)
				}
			})
		}
		if (fids.length > 0) {
			// 请求用户信息。请求完毕后，存储用户信息
			const db = cloud.database()
			const dbCmd = db.command
			name = getDbName(name, space)
			db.collection(name).where({_id: dbCmd.in(fids)}).field(field).get().then(res => {
				const sarr = [] // 需要存储的方法
				res.result.data.map(item => {
					arr.push(item)
					// 并且依次存储
					sarr.push(new Promise((resolve, reject) => {
						core.storage.setData(`${item._id}_user`, JSON.stringify(item)).then(res => {
							resolve(item._id)
						}).catch(err => {
							resolve()
						})
					}))
				})
				resolve(arr)
				// 依次将存储过的用户id计入缓存，并且最后记录所有id
				Promise.all(sarr).then(res => {
					res.map(id => {
						if (id && core.storage.userInfoIds.indexOf(id) === -1) {
							core.storage.userInfoIds.push(id)
						}
					})
					// 最后要记录所有的id
					core.storage.setData(core.storage.ClearKey.UserInfoCache, JSON.stringify(core.storage.userInfoIds))
				})
			})
		} else {
			resolve(arr)
		}
	})
}

// 默认的key值
const default_ckey = 'user_id,creator,alert_user'
// 默认的用户数据库
const default_name = 'a-user'
// 默认的用户数据库的对应字段
const default_fkey = '_id'
// 默认的返回字段
const default_field = 'name,phone,gender,nickname'

/**
 * 所有出现过的用户信息，都将缓存起来
 * 默认凡字段是user_id的，不需要联表操作，自动查询给出一个user_id_copy的字段来映射。
 * 也就是说原数据是数组，那就对应数组。原数据是单个字符串，那就是对象
 * data：是请求得到的主要数据。可以是对象或者数组
 * userKeys：需要处理的字段信息。可以是字符串，可以带逗号，最终会转化为对象数组。所以建议使用数组，建议具体元素是对象，指定具体的用户信息要求
 * 比如：{
	 ckey: 'user_id',
	 space: 'capfer',
	 name: 'a-user',
	 fkey: '_id',
	 field: 'name,phone'
 }
 获取到用户信息后，将会缓存起来
 */
module.exports = (data, config) => {
	// 要处理的用户信息字段，是否需要最新的用户信息
	var {userKeys = default_ckey, reuserinfo} = config || {}
	const default_space = core.request.basedata.current
	return new Promise((resolve, reject) => {
		if (data) {
			var isArray = Array.isArray(data)
			const success = () => {
				if (isArray) {
					resolve(data)
				} else {
					resolve(data[0])
				}
			}
			if (!isArray) {
				data = [data]
			}
			if (typeof(userKeys) === 'string') {
				userKeys = userKeys.split(',')
			}
			if (Object.prototype.toString.call(userKeys) === '[object Object]') {
				userKeys = [userKeys]
			}
			if (Array.isArray(data) && Array.isArray(userKeys)) {
				if (userKeys.length === 0) {
					userKeys = ['user_id']
				}
				for (let i = 0; i < userKeys.length; i++) {
					if (typeof(userKeys[i]) === 'string') {
						userKeys[i] = {
							ckey: userKeys[i],
							space: default_space,
							name: default_name,
							fkey: default_fkey,
							field: default_field
						}
					} else if (Object.prototype.toString.call(userKeys[i]) === '[object Object]') {
						if (!userKeys[i].ckey) {
							userKeys[i].ckey = default_ckey
						}
						if (!userKeys[i].space) {
							userKeys[i].space = default_space
						}
						if (!userKeys[i].name) {
							userKeys[i].name = default_name
						}
						if (!userKeys[i].fkey) {
							userKeys[i].fkey = default_fkey
						}
						if (!userKeys[i].field) {
							userKeys[i].field = default_field
						}
					}
				}
				// 不同的数据库下查询用户信息
				const tempObj = {}
				data.map(item => {
					userKeys.map(obj => {
						const {ckey, space, name, fkey, field} = obj
						if (item[ckey] && !item[`${ckey}_copy`] && item[ckey] !== []) {
							// 存在该字段值，并且没有通过联表查询
							var objKey = `${space}-${name}`
							if (tempObj[objKey]) {
								if (Array.isArray(item[ckey])) {
									item[ckey].map(id => {
										if (tempObj[objKey].ids.indexOf(id) === -1) {
											tempObj[objKey].ids.push(id)
										}
									})
								} else {
									if (tempObj[objKey].ids.indexOf(item[ckey]) === -1) {
										tempObj[objKey].ids.push(item[ckey])
									}
								}
								if (tempObj[objKey].ckeys.indexOf(ckey) === -1) {
									tempObj[objKey].ckeys.push(ckey)
								}
								if (tempObj[objKey].fkeys.indexOf(fkey) === -1) {
									tempObj[objKey].fkeys.push(fkey)
								}
							} else {
								const ids = []
								if (Array.isArray(item[ckey])) {
									item[ckey].map(id => {
										if (ids.indexOf(id) === -1) {
											ids.push(id)
										}
									})
								} else {
									ids.push(item[ckey])
								}
								tempObj[objKey] = {
									space, name, 
									field, ids,
									ckeys: [ckey],
									fkeys: [fkey]
								}
							}
						}
					})
				})
				// 通过ckey查找准确的fkey
				const getFkey = (s, n, c) => {
					for (let i = 0; i < userKeys.length; i++) {
						const {space, name, ckey, fkey} = userKeys[i]
						if (space === s && name === n && ckey === c) {
							return fkey
						}
					}
				}
				const arr = []
				Object.keys(tempObj).forEach(k => {
					var {space, name, ids, field, ckeys, fkeys} = tempObj[k]
					const cloud = uniCloud.init(getSpaceBase(core.request.basedata[space]))
					if (cloud) {
						arr.push(new Promise((resolve, reject) => {
							// 获取用户信息后，给数据源相应的字段赋值
							getUserInfo(cloud, space, name, field, ids, reuserinfo).then(res => {
								data.map(obj => {
									ckeys.map(key => {
										if (obj[key]) {
											const fkey = getFkey(space, name, key)
											if (fkey) {
												if (typeof(obj[key]) === 'string') {
													for (let i = 0; i < res.length; i++) {
														if (res[i][fkey] === obj[key]) {
															obj[`${key}_copy`] = res[i]
															break
														}
													}
												} else if (Array.isArray(obj[key]) && obj[key].length > 0) {
													const a = [] // 按顺序添加
													obj[key].map(k => {
														for (let i = 0; i < res.length; i++) {
															if (res[i][fkey] === k) {
																a.push(res[i])
															}
														}
													})
													obj[`${key}_copy`] = a
												}
											}
										}
									})
								})
								resolve()
							})
						}))
					}
				})
				if (arr.length > 0) {
					Promise.all(arr).then(res => {
						success(data)
					}).catch(err => {
						success(data)
					})
				} else {
					success(data)
				}
			} else {
				success(data)
			}
		} else {
			resolve(data)
		}
	})
}